﻿using System.Buffers;
using System.Net.WebSockets;
using System.Text;

using GCC.Container.Abstracts;
using GCC.Container.LogProviders;

using Newtonsoft.Json;

namespace GCC.APIContainer.WSManager
{
    /// <summary>
    /// 容器websocket信息对象
    /// </summary>
    internal class GCCTextWSInfo : AbsWebsocketDataClient<string>, IDisposable
    {

        /// <summary>
        /// websocket客户端
        /// </summary>
        public WebSocket Client { get; init; }

        /// <summary>
        /// 内存池
        /// </summary>
        private readonly MemoryPool<byte> _memoryPool = MemoryPool<byte>.Shared;
        /// <summary>
        /// 取消token
        /// </summary>
        private readonly CancellationTokenSource _cancellToken = new();
        /// <summary>
        /// 是否已经销毁
        /// </summary>
        private bool _disposed;


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="client">websocket客户端</param>
        public GCCTextWSInfo(AbsGCCContext context, WebSocket client) : base(context, GCCLoggerProvider.Instance!.CreateLogger<GCCTextWSInfo>())
        {
            Context = context;
            Client = client;
        }



        /// <summary>
        /// 析构函数
        /// </summary>
        ~GCCTextWSInfo()
        {
            Dispose(false);
        }

        /// <summary>
        /// 销毁模型
        /// </summary>
        /// <param name="flag">是否是用户主动调用</param>
        protected override void Dispose(bool flag)
        {
            if (_disposed)
            {
                return;
            }
            _disposed = true;

            try
            {
                _memoryPool.Dispose();
                Client.CloseAsync(WebSocketCloseStatus.Empty, "", CancellationToken.None).Wait();
                Client.Dispose();
            }
            catch (Exception ex)
            {
                _logger.Error("GCCWSInfo dispose error.", exception: ex);
            }
            base.Dispose(flag);
        }


        /// <summary>
        /// 启动服务
        /// </summary>
        /// <returns></returns>
        public override async Task StartJob()
        {
            using var wsBufferOwner = _memoryPool.Rent(1024 * 400);
            var wsBuffer = wsBufferOwner.Memory[..1024];
            while (!_cancellToken.Token.IsCancellationRequested && Client.State == WebSocketState.Open)
            {
                try
                {
                    var result = await Client.ReceiveAsync(wsBuffer, CancellationToken.None);
                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        _logger.Information($"Websocket receive close request, shutdown.");
                        break;
                    }
                    if (result.MessageType != WebSocketMessageType.Text)
                    {
                        _logger.Error($"This websocket just can receive Text message, Shutdown!");
                        break;
                    }
                    if (result.EndOfMessage != true)
                    {
                        _logger.Error($"This websocket just can receive less than 400KB Message, Shutdown!");
                        break;
                    }

                    var tCMDeviceRequest = JsonConvert.DeserializeObject<TCMDeviceRequest>(Encoding.UTF8.GetString(wsBuffer[..result.Count].Span));
                    if (tCMDeviceRequest != null&&tCMDeviceRequest.site_id>0)
                    {
                        _=Context.Remove(tCMDeviceRequest.site_id.ToString());
                        Context.Set<TCMDeviceRequest>(tCMDeviceRequest.site_id.ToString(), tCMDeviceRequest, new CacheItemSettings()
                        {
                            SaveToAll = true,
                            SlidingExpiration = TimeSpan.FromSeconds(60*60*2),
                        }).Wait();
                    }

                    GotTextMessage(Encoding.UTF8.GetString(wsBuffer[..result.Count].Span));
                }
                catch (WebSocketException ex)
                {
                    _logger.Error($"websocket got error.Close", exception: ex);
                    break;
                }
                catch (Exception ex)
                {
                    _logger.Error($"websocket got error.Close", exception: ex);
                    continue;
                }
            }
        }





        /// <summary>
        /// 发送文本消息
        /// </summary>
        /// <param name="text"></param>
        public override async void SendTextMessage(string text)
        {
            if (Client.State == WebSocketState.Open)
            {
                await Client.SendAsync(Encoding.UTF8.GetBytes(text), WebSocketMessageType.Text, true, _cancellToken.Token);
            }

        }
    }
}
